package com.boruan.shengtangfeng.api.config;


import com.boruan.shengtangfeng.core.utils.DateUtils;
import org.apache.xmlbeans.InterfaceExtension;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component //声明这是一个组件
@Aspect //声明这是一个切面Bean
public class WebLogAspect {

    private static Logger log = LoggerFactory.getLogger(WebLogAspect.class);

    //配置切入点,该方法无方法体,主要为方便同类中其他方法使用此处配置的切入点,用来指明要在哪些方法切入。
    @Pointcut("execution(public * com.boruan.shengtangfeng.api.controller..*.*(..))")
    public void webLog() {
    }

    /*
     * 配置前置通知,使用在方法aspect()上注册的切入点
     * 同时接受JoinPoint切入点对象,可以没有该参数
     * 通过 Advice 相关注解来说明在切入方法的什么位置做什么事
     */
    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) {
        for (Object object : joinPoint.getArgs()) {
            if (object instanceof MultipartFile || object instanceof HttpServletRequest || object instanceof HttpServletResponse) {
                continue;
            }
            try {
                StringBuffer sb = new StringBuffer();
                sb.append(DateUtils.getDate("yyyy-MM-dd HH:mm:ss") + " ");
                Object[] args = joinPoint.getArgs(); // 参数值
                // Target（目标对象）：织入 Advice 的目标对象.。
                sb.append(joinPoint.getSignature().getName() + "  请求参数 ");
                String[] argNames = ((MethodSignature) joinPoint.getSignature()).getParameterNames(); // 参数名
                for (int i = 0; i < argNames.length; i++) {
                    sb.append(argNames[i] + ":" + args[i] + " ");
                }
                long startTime = System.currentTimeMillis();
                System.out.println(sb.toString());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


    //配置后置通知,使用在方法aspect()上注册的切入点
   /* @After("webLog()")
    public void after(JoinPoint joinPoint) {
        StringBuffer sb = new StringBuffer();
        Object[] args = joinPoint.getArgs(); // 参数值
        // Target（目标对象）：织入 Advice 的目标对象.。
        sb.append(joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "  请求参数 ");

    }*/

    // 调用实际的目标方法，可以在目标方法调用前做一些操作，
    // 也可以在目标方法调用后做一些操作。使用场景有：事物管理、权限控制，日志打印、性能分析等等
    @Around("webLog()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        //开始时间
        long start = System.currentTimeMillis();
        //执行方法才会真正的执行实际被代理的方法
        Object result = point.proceed();
        long end = System.currentTimeMillis();
        MethodSignature signature = (MethodSignature) point.getSignature();

        //请求的方法名
        String className = point.getTarget().getClass().getName();
        String methodName = signature.getName();
        // log.info("【接口执行时间】接口名：{}.{},执行时间:{}毫秒", className, methodName, (end - start));

        StringBuffer sb = new StringBuffer();
        sb.append(DateUtils.getDate() + " ");
        Object[] args = point.getArgs(); // 参数值
        // Target（目标对象）：织入 Advice 的目标对象.。
        sb.append(point.getTarget().getClass().getName() + "." + point.getSignature().getName() + "  请求参数 ");
        String[] argNames = ((MethodSignature) point.getSignature()).getParameterNames(); // 参数名
        for (int i = 0; i < argNames.length; i++) {
            sb.append(argNames[i] + ":" + args[i] + " ");
        }
        return result;
    }


    //配置环绕通知,使用在方法aspect()上注册的切入点
   /* @Around("webLog()")
    public void around(JoinPoint joinPoint) {

    }*/

    //配置后置返回通知,使用在方法aspect()上注册的切入点
    /*@AfterReturning("webLog()")
    public void afterReturn(JoinPoint joinPoint) {
    }*/
}
